// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "zencore.h"

#if ZEN_COMPILER_MSC
#	include <intrin.h>
#elif ZEN_ARCH_X64
#	include <x86intrin.h>
#endif

#include <stdint.h>

namespace zen {

// High frequency timers

ZENCORE_API uint64_t GetHifreqTimerValue();
ZENCORE_API uint64_t GetHifreqTimerFrequency();
ZENCORE_API double	 GetHifreqTimerToSeconds();
ZENCORE_API uint64_t GetHifreqTimerFrequencySafe();	 // May be used during static init

class Stopwatch
{
public:
	inline Stopwatch() : m_StartValue(GetHifreqTimerValue()) {}

	inline uint64_t GetElapsedTimeMs() const { return (GetHifreqTimerValue() - m_StartValue) * 1'000 / GetHifreqTimerFrequency(); }
	inline uint64_t GetElapsedTimeUs() const { return (GetHifreqTimerValue() - m_StartValue) * 1'000'000 / GetHifreqTimerFrequency(); }
	inline uint64_t GetElapsedTicks() const { return GetHifreqTimerValue() - m_StartValue; }
	inline void		Reset() { m_StartValue = GetHifreqTimerValue(); }

	static inline uint64_t GetElapsedTimeMs(uint64_t Ticks) { return Ticks * 1'000 / GetHifreqTimerFrequency(); }
	static inline uint64_t GetElapsedTimeUs(uint64_t Ticks) { return Ticks * 1'000'000 / GetHifreqTimerFrequency(); }

private:
	uint64_t m_StartValue;
};

// Low frequency timers

namespace detail {
	extern ZENCORE_API uint64_t g_LofreqTimerValue;
}  // namespace detail

inline uint64_t
GetLofreqTimerValue()
{
	return detail::g_LofreqTimerValue;
}

ZENCORE_API void	 UpdateLofreqTimerValue();
ZENCORE_API uint64_t GetLofreqTimerFrequency();

void timer_forcelink();	 // internal

}  // namespace zen
